package com.icee.myth.server.activity.normalActivity;

import com.icee.myth.log.GameLogger;
import com.icee.myth.log.message.FileDebugGameLogMessage;
import com.icee.myth.log.message.builder.GameLogMessageBuilder;
import com.icee.myth.protobuf.InternalCommonProtocol.DBNormalActivityProto;
import com.icee.myth.protobuf.InternalCommonProtocol.DBNormalActivityStatusProto;
import com.icee.myth.protobuf.builder.ClientToMapBuilder;
import com.icee.myth.server.GameServer;
import com.icee.myth.server.actor.Human;
import com.icee.myth.utils.Consts;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 *
 * @author liuxianke
 */
public class NormalActivity {
    public final Human human;
    public final TreeMap<Integer, NormalActivityStatus> activityStatuses = new TreeMap<Integer, NormalActivityStatus>();    // 活动状态，key为活动id
    public int lastGetRewardDay;
    private long nextAllowOperateTime;  // 下一次活动操作许可时间（防止被攻击）

    public NormalActivity(Human human, DBNormalActivityProto normalActivityProto) {
        this.human = human;

        if (normalActivityProto != null) {
            // 判断所记录的活动项是否未过期，对过期的不再保留
            lastGetRewardDay = normalActivityProto.getLastGetRewardDay();
            List<DBNormalActivityStatusProto> activityStatusProtos = normalActivityProto.getActivityStatusesList();
            if (!activityStatusProtos.isEmpty()) {
                for (DBNormalActivityStatusProto activityStatusProto : activityStatusProtos) {
                    int activityId = activityStatusProto.getActivityId();
                    NormalActivityTemplate activityTemplate = NormalActivityTemplates.INSTANCE.getNormalActivityTemplate(activityId);
                    // 判断活动过期的标准是找不到相关活动或活动结束时间已到（注意：过期活动已在主循环中删除）
                    if (activityTemplate != null) {
                        activityStatuses.put(activityId, new NormalActivityStatus(activityStatusProto));
                    }
                }
            }

            refresh();
        } else {
            lastGetRewardDay = (int) ((GameServer.INSTANCE.getCurrentTime() + Consts.JET_LAG) / (Consts.MILSECOND_ONE_DAY));
        }
    }

    public DBNormalActivityProto buildDBNormalActivityProto() {
        DBNormalActivityProto.Builder builder1 = DBNormalActivityProto.newBuilder();
        builder1.setLastGetRewardDay(lastGetRewardDay);

        for (NormalActivityStatus normalActivityStatus : activityStatuses.values()) {
            builder1.addActivityStatuses(normalActivityStatus.buildDBNormalActivityStatusProto());
        }

        return builder1.build();
    }

    public void getActivityList() {
        long currentTime = GameServer.INSTANCE.getCurrentTime();
        if (currentTime >= nextAllowOperateTime) {
            nextAllowOperateTime = currentTime + Consts.MILSECOND_1SECOND;  // cooldown 1 second
            human.sendMessage(ClientToMapBuilder.buildNormalActivityOperateTime(nextAllowOperateTime));

            human.sendMessage(ClientToMapBuilder.buildNormalActivityList(NormalActivityTemplates.INSTANCE.buildNormalActivitiesProto()));
        } else {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                    "Player[" + human.id + "] get activity list error because not cooldown."));
        }
    }

    public void getActivityItemList(int activityId) {
        long currentTime = GameServer.INSTANCE.getCurrentTime();
        if (currentTime >= nextAllowOperateTime) {
            nextAllowOperateTime = currentTime + Consts.MILSECOND_1SECOND;  // cooldown 1 second
            human.sendMessage(ClientToMapBuilder.buildNormalActivityOperateTime(nextAllowOperateTime));

            refresh();

            NormalActivityTemplate normalActivityTemplate = NormalActivityTemplates.INSTANCE.getNormalActivityTemplate(activityId);

            if (normalActivityTemplate != null) {
                NormalActivityStatus normalActivityStatus = activityStatuses.get(activityId);

                human.sendMessage(ClientToMapBuilder.buildNormalActivityItemList(normalActivityTemplate.staticInfo.buildNormalActivityItemsProto(normalActivityStatus)));
            } else {
                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                        "Player[" + human.id + "] can't get normal activity[" + activityId + "] item list because activity not found."));
            }
        } else {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                    "Player[" + human.id + "] get activity item list error because not cooldown."));
        }
    }

    public void enterActivityStage(int activityId, int itemId, int helperId) {
        long currentTime = GameServer.INSTANCE.getCurrentTime();
        if (currentTime >= nextAllowOperateTime) {
            nextAllowOperateTime = currentTime + Consts.MILSECOND_1SECOND;  // cooldown 1 second
            human.sendMessage(ClientToMapBuilder.buildNormalActivityOperateTime(nextAllowOperateTime));

            refresh();

            NormalActivityItem item = getActivityItem(activityId, itemId);

            if (item != null) {
                NormalActivityStatus activityStatus = getActivityStatus(activityId);
                NormalActivityItemStatus activityItemStatus = activityStatus.getItemStatus(itemId);

                item.enterActivityStage(human, activityId, activityItemStatus, helperId);
            } else {
                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                        "Player[" + human.id + "] can't enter activity item[" + itemId + "] stage."));
            }
        } else {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                    "Player[" + human.id + "] enter activity stage error because not cooldown."));
        }
    }

    // 过关
    public void finishState(int activityId, int itemId) {
        refresh();
        
        NormalActivityItemStatus activityItemStatus = getActivityItemStatus(activityId, itemId);

        if (activityItemStatus != null) {
            activityItemStatus.value++;
        }
    }

    // 充值
    public void chargeGold(int num) {
        // 修改所有进行中的充值活动状态
        refresh();

        for (NormalActivityTemplate normalActivityTemplate : NormalActivityTemplates.INSTANCE.templates.values()) {
            // 判断活动是否已开始（注意：过期活动已在主循环中删除）
            NormalActivityStaticInfo normalActivityStaticInfo = normalActivityTemplate.staticInfo;

            long activityStartTime = (normalActivityStaticInfo.startTime != null)?normalActivityStaticInfo.startTime.getTime(): GameServer.INSTANCE.openTime.getTime() + normalActivityStaticInfo.startRelativeTime;
            if (activityStartTime < GameServer.INSTANCE.getCurrentTime()) {
                for (NormalActivityItem normalActivityItem : normalActivityStaticInfo.items) {
                    if (normalActivityItem.type == Consts.NORMAL_ACTIVITY_ITEM_TYPE_CHARGE) {
                        NormalActivityItemStatus normalActivityItemStatus = getActivityItemStatus(normalActivityStaticInfo.id, normalActivityItem.id);
                        normalActivityItemStatus.value += num;
                    }
                }
            }
        }
    }

    // 消费
    public void consumeGold(int num) {
        // 修改所有进行中的消费活动状态
        refresh();

        for (NormalActivityTemplate normalActivityTemplate : NormalActivityTemplates.INSTANCE.templates.values()) {
            // 判断活动是否已开始（注意：过期活动已在主循环中删除）
            NormalActivityStaticInfo normalActivityStaticInfo = normalActivityTemplate.staticInfo;

            long activityStartTime = (normalActivityStaticInfo.startTime != null)?normalActivityStaticInfo.startTime.getTime(): GameServer.INSTANCE.openTime.getTime() + normalActivityStaticInfo.startRelativeTime;
            if (activityStartTime < GameServer.INSTANCE.getCurrentTime()) {
                for (NormalActivityItem normalActivityItem : normalActivityStaticInfo.items) {
                    if (normalActivityItem.type == Consts.NORMAL_ACTIVITY_ITEM_TYPE_CONSUME) {
                        NormalActivityItemStatus normalActivityItemStatus = getActivityItemStatus(normalActivityStaticInfo.id, normalActivityItem.id);
                        normalActivityItemStatus.value += num;
                    }
                }
            }
        }
    }

    public void getReward(int activityId, int itemId) {
        refresh();

        NormalActivityItem item = getActivityItem(activityId, itemId);

        if (item != null) {
            NormalActivityStatus activityStatus = getActivityStatus(activityId);
            NormalActivityItemStatus activityItemStatus = activityStatus.getItemStatus(itemId);

            item.getReward(human, activityId, activityItemStatus);
        } else {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                    "Player[" + human.id + "] can't enter activity item[" + itemId + "] stage."));
        }
    }

    private void refresh() {
        // 若最后领奖日期与当前日期不是同一天，刷新领奖状态
        int currentDay = (int) ((GameServer.INSTANCE.getCurrentTime() + Consts.JET_LAG) / (Consts.MILSECOND_ONE_DAY));
        if (currentDay > lastGetRewardDay) {
            //重置所有可每日领取的项目
            resetItemRewardStatus();

            lastGetRewardDay = currentDay;
        }
    }

    private NormalActivityStatus getActivityStatus(int activityId) {
        NormalActivityStatus activityStatus = activityStatuses.get(activityId);

        if (activityStatus == null) {
            activityStatus = new NormalActivityStatus(activityId);
            activityStatuses.put(activityId, activityStatus);
        }

        return activityStatus;
    }

    private NormalActivityItemStatus getActivityItemStatus(int activityId, int itemId) {
        NormalActivityItem item = getActivityItem(activityId, itemId);

        if (item != null) {
            NormalActivityStatus activityStatus = getActivityStatus(activityId);
            return activityStatus.getItemStatus(itemId);
        } else {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                    "Player[" + human.id + "] can't get activity item[" + itemId + "] status."));

            return null;
        }
    }

    // 获取进行中的活动项
    private NormalActivityItem getActivityItem(int activityId, int itemId) {
        NormalActivityTemplate activityTemplate = NormalActivityTemplates.INSTANCE.getNormalActivityTemplate(activityId);
        // 判断活动是否未开始（注意：过期活动已在主循环中删除）
        if (activityTemplate != null) {
            NormalActivityStaticInfo staticInfo = activityTemplate.staticInfo;
            long activityStartTime = (staticInfo.startTime != null)?staticInfo.startTime.getTime(): GameServer.INSTANCE.openTime.getTime() + staticInfo.startRelativeTime;
            if (activityStartTime < GameServer.INSTANCE.getCurrentTime()) {
                if (staticInfo.items.length > itemId) {
                    return staticInfo.items[itemId];
                } else {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                            "Player[" + human.id + "] can't get normal activity item[" + itemId + "] because activity[" + activityId + "] has not such item."));
                }
            } else {
                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                        "Player[" + human.id + "] can't get normal activity item[" + itemId + "] because activity[" + activityId + "] is not started."));
            }
        } else {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                    "Player[" + human.id + "] can't get normal activity item[" + itemId + "] because activity[" + activityId + "] not exist."));
        }

        return null;
    }

    private void resetItemRewardStatus() {
        // 重置所有可每日领取的项目
        Iterator<Map.Entry<Integer, NormalActivityStatus>> iterator = activityStatuses.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Integer, NormalActivityStatus> entry = iterator.next();
            int activityId = entry.getKey();
            NormalActivityStatus status = entry.getValue();

            // 若活动过期，删除项目
            NormalActivityTemplate activityTemplate = NormalActivityTemplates.INSTANCE.getNormalActivityTemplate(activityId);
            if (activityTemplate != null) {
                for (NormalActivityItem activityItem : activityTemplate.staticInfo.items) {
                    if (activityItem.isDaily) {
                        status.removeItemStatus(activityItem.id);
                    }
                }
            } else {
                // 活动过期，删除项目状态
                iterator.remove();
            }
        }
    }
}
